﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Per_pixel_OCR;
using System.IO;
using Character_part_tagger;

namespace Character_part_tagger
{
    public partial class Form1 : Form
    {
        string defaultSource = "C:\\train.data";
        Digit[] inputs;

        int picWidth;
        int picHeight;

        int width = 28;
        int height = 28;

        int pixelWidth = 20;
        int pixelHeight = 20;

        Pen linePen = new Pen(Color.Red);
        
        private int characterID = 0;
        public int CharacterID
        {
            get
            {
                return characterID;
            }
            set
            {
                if (value >= inputs.Length)
                    value = 0;
                if (value < 0)
                    value = inputs.Length - 1;

                characterID = value;
                
                lblCurrent.Text = inputs[characterID].DigitValue.ToString();
                txtCharacterID.Text = characterID.ToString();
            }
        }
        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (File.Exists(defaultSource))
                statusLabel.Text = defaultSource + " is loaded!";
            else
                statusLabel.Text = defaultSource + " couldn't found. Please load another file!";

            this.pictureBox1.Width = width * pixelWidth + 1;
            this.pictureBox1.Height = height * pixelHeight + 1;
            this.pictureBox2.Width = width * pixelWidth + 1;
            this.pictureBox2.Height = height * pixelHeight + 1;

            this.picWidth = this.pictureBox1.Width;
            this.picHeight = this.pictureBox1.Height;

            inputs = FileOperations.ReadNewDB(defaultSource);
           
            foreach (Control control in this.Controls)
            {
                control.PreviewKeyDown += new PreviewKeyDownEventHandler(control_PreviewKeyDown);
            }

            this.CharacterID = 0;

            Invalidate(true);
        }

        bool IsOk()
        {
            if (cmbSelection.Text == "All")
                return true;
            else
            {
                if (inputs[CharacterID].DigitValue == Convert.ToInt32(cmbSelection.Text))
                    return true;
            }

            return false;
        }

        void control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Right)
            {
                do
                {
                    if (CharacterID < inputs.Length - 1)
                        CharacterID++;
                    else
                        CharacterID = 0;
                }
                while (!IsOk());                
            }
            else if (e.KeyCode == Keys.Left)
            {
                do
                {
                    if (CharacterID > 0)
                        CharacterID--;
                    else
                        CharacterID = inputs.Length - 1;
                }
                while (!IsOk());
            }

            Refresh();

            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
                e.IsInputKey = true;
        }

        private void Refresh()
        {
            pictureBox1.Invalidate();
            pictureBox1.Update();

            this.Update();
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Image img = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            Graphics g = Graphics.FromImage(img);

            // Draw the red lines.
            int i;
            for (i = 0; i < width; i++)
            {
                g.DrawLine(linePen, 0, pixelHeight * i, picWidth, pixelHeight * i);
            }
            g.DrawLine(linePen, 0, pixelHeight * i, picWidth, pixelHeight * i);

            for (i = 0; i < width; i++)
            {
                g.DrawLine(linePen, pixelWidth * i, 0, pixelWidth * i, picHeight);
            }
            g.DrawLine(linePen, pixelWidth * i, 0, pixelWidth * i, picHeight);

            DrawMatrix(this.inputs[CharacterID].OriginalGrayscaleMatrix, g);

            pictureBox1.Image = img;
        }

        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            Image img = new Bitmap(pictureBox2.Width, pictureBox2.Height);
            Graphics g = Graphics.FromImage(img);

            // Draw the red lines.
            int i;
            for (i = 0; i < width; i++)
            {
                g.DrawLine(linePen, 0, pixelHeight * i, picWidth, pixelHeight * i);
            }
            g.DrawLine(linePen, 0, pixelHeight * i, picWidth, pixelHeight * i);

            for (i = 0; i < width; i++)
            {
                g.DrawLine(linePen, pixelWidth * i, 0, pixelWidth * i, picHeight);
            }
            g.DrawLine(linePen, pixelWidth * i, 0, pixelWidth * i, picHeight);

            DrawMatrix2(this.inputs[CharacterID].TagMatrix, g);

            pictureBox2.Image = img;
        }

        private void DrawMatrix(byte[,] matrix, Graphics g)
        {
            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    int temp = 255 - matrix[i,j];
                    Color c = Color.FromArgb(temp, temp, temp);

                    g.FillRectangle(new SolidBrush(c), new Rectangle(j * pixelHeight + 1, i * pixelWidth + 1, pixelWidth - 1, pixelHeight - 1));
                }
            }
        }

        private void DrawMatrix2(byte[,] matrix, Graphics g)
        {
            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    Color c = IDToColor(matrix[i, j]);

                    g.FillRectangle(new SolidBrush(c), new Rectangle(j * pixelHeight + 1, i * pixelWidth + 1, pixelWidth - 1, pixelHeight - 1));
                }
            }
        }

        private Color IDToColor(int id)
        {
            Color c;
            
            switch (id)
            {
                case 255: 
                    c = Color.White;
                    break;
                case 254: // unknown
                    c = Color.Black;
                    break;
                case 0:
                    c = Color.Blue;
                    break;
                case 1:
                    c = Color.Green;
                    break;
                case 2:
                    c = Color.Orange;
                    break;
                case 3:
                    c = Color.Yellow;
                    break;
                case 4:
                    c = Color.Pink;
                    break;
                case 5:
                    c = Color.Gray;
                    break;
                case 6:
                    c = Color.CadetBlue;
                    break;
                case 7:
                    c = Color.IndianRed;
                    break;
                case 8:
                    c = Color.Khaki;
                    break;
                case 9:
                    c = Color.Indigo;
                    break; 
                default:
                    throw new Exception("Unknown color!");
            }

            return c;
        }
        
        private void txtCharacterID_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 13) // enter
            {
                string str = txtCharacterID.Text;
                int value = 0;
                if (int.TryParse(str, out value))
                    CharacterID = value;                       
                e.Handled = true;
            }
            else if (Char.IsDigit(e.KeyChar) || e.KeyChar == 8) // digit or backspace
            {

            }
            else
            {
                e.Handled = true;
            }
        }

        private void exitAltF4ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }
        
        private void cmbSelection_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.txtCharacterID.Focus();
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            int x = e.X / pixelWidth;
            int y = e.Y / pixelHeight;

            lblPixelValue.Text = this.inputs[characterID].OriginalGrayscaleMatrix[y, x].ToString();

            this.Refresh();
        }

        private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
        {
            int x = e.X / pixelWidth;
            int y = e.Y / pixelHeight;

            lblPixelValue.Text = this.inputs[characterID].TagMatrix[y, x].ToString();

            this.Refresh();
        }
    }
}
